package com.breeze.components.core.util.ip;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.regex.Pattern;
import lombok.extern.slf4j.Slf4j;

/**
 * @author breeze
 */
@Slf4j
public class IpUtil {

  public static final String UNKNOWN = "unknown";
  public static final String LOCALHOST = "localhost";
  public static final String LOCAL_IP = "127.0.0.1";

  public static final String INNER_IP_REGEX =
      "^(127\\.0\\.0\\.\\d{1,3})|(localhost)|(10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(172\\.((1[6-9])|(2\\d)|(3[01]))\\.\\d{1,3}\\.\\d{1,3})|(192\\.168\\.\\d{1,3}\\.\\d{1,3})$";
  public static final Pattern INNER_IP_PATTERN = Pattern.compile(INNER_IP_REGEX);

  private IpUtil() {}

  public static boolean isInnerIp(String ip) {
    return INNER_IP_PATTERN.matcher(ip).matches() || isLocalHost(ip);
  }

  public static boolean isLocalHost(String ipAddress) {
    InetAddress ia = null;
    try {
      InetAddress ad = InetAddress.getByName(ipAddress);
      byte[] ip = ad.getAddress();
      ia = InetAddress.getByAddress(ip);
    } catch (UnknownHostException e) {
      log.error("解析Ip失败", e);
    }
    if (ia == null) {
      return false;
    }
    return ia.isSiteLocalAddress() || ia.isLoopbackAddress();
  }

  public static boolean isValidIpv4(String inetAddress) {
    return Validator.isIpv4(inetAddress);
  }

  public static boolean isValidIpv6(String inetAddress) {
    return Validator.isIpv6(inetAddress);
  }

  public static String getIpAddr(final HttpServletRequest request) {
    // X-Real-IP：nginx服务代理
    String ip = request.getHeader("X-Real-IP");
    // X-Forwarded-For：Squid 服务代理
    if (checkIp(ip)) {
      ip = request.getHeader("X-Forwarded-For");
    }
    // Proxy-Client-IP：apache 服务代理
    if (checkIp(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
    }
    // WL-Proxy-Client-IP：web logic 服务代理
    if (checkIp(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    // HTTP_CLIENT_IP：有些代理服务器
    if (checkIp(ip)) {
      ip = request.getHeader("HTTP_CLIENT_IP");
    }
    if (checkIp(ip)) {
      ip = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (checkIp(ip)) {
      ip = request.getRemoteAddr();
    }

    // 如果是多级代理，那么取第一个ip为客户ip
    if (ip != null && ip.contains(",")) {
      ip = ip.substring(ip.lastIndexOf(",") + 1).trim();
    }
    // 本机地址
    if (!StrUtil.isEmpty(ip) && "0:0:0:0:0:0:0:1".equals(ip)) {
      ip = "localhost";
    }
    return ip;
  }

  private static boolean checkIp(String ip) {
    return StrUtil.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip);
  }

  public static boolean isLocal(String ip) {
    return LOCALHOST.equals(ip) || LOCAL_IP.equals(ip);
  }

  public static String getServerIp() {
    String ip = "";
    try {
      Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
      while (interfaces.hasMoreElements()) {
        NetworkInterface networkInterface = interfaces.nextElement();
        if (networkInterface.isLoopback() || !networkInterface.isUp()) {
          continue;
        }
        Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
        while (addresses.hasMoreElements()) {
          InetAddress inetAddress = addresses.nextElement();
          if (inetAddress.isLoopbackAddress()) {
            continue;
          }
          if (inetAddress.getAddress().length == 4) {
            ip = inetAddress.getHostAddress();
          }
        }
      }
    } catch (SocketException ignore) {

    }
    return ip;
  }
}
